#!/usr/bin/env python
# -*-coding:UTF-8-*-

"""
简单用函数实现map，reduce，fileter
"""
from functools import reduce
from collections import Iterable
import copy


def fn(x):
    return x * x


def fn1(x, y):
    return x + y


def fn2(n):
    return n % 2 == 1


class IterableError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)


iterableError = IterableError('Iterable is not Iterable')


def map_self(fx, list_n):
    if not isinstance(list_n, Iterable):
        raise iterableError
    list_copy = copy.deepcopy(list_n)
    for x in range(len(list_copy)):
        list_copy[x] = fx(list_copy[x])
    return list_copy


def reduce_self(fx, list_n):
    """
    这里是不是也可以 raise 下异常呢？
    """
    list_copy = copy.deepcopy(list_n)
    res = list_copy[0]
    for x in list_copy[1:]:
        res = fx(res, x)
    return res


def filter_self(fx, list_n):
    list_copy = copy.deepcopy(list_n)
    res = []
    for x in list_copy:
        if fn2(x):
            res.append(x)
    return res


def main():
    list1 = list(range(1, 10))
    list2 = [1, 3, 5, 7, 9]
    list3 = [1, 2, 4, 5, 6, 9, 10, 15]

    # map
    ret = list(map(fn, list1))
    str1 = list(map(str, list1))
    ret1 = map_self(fn, list1)
    str2 = map_self(str, list1)
    print('{}\n{}\n{}\n{}\n{}\n{}\n'.format('map'.center(20, '-'), ret, str1, 'map self'.center(20, '-'), ret1, str2))

    # error test
    try:
        map_self(fn, 12345)
    except Exception as e:
        print(e)

    # reduce
    ret1 = reduce(fn1, list2)
    ret2 = reduce_self(fn1, list2)
    print('{}\n{}\n{}\n{}\n'.format('reduce'.center(20, '-'), ret1, 'reduce self'.center(20, '-'), ret2))

    # filter
    ret1 = list(filter(fn2, list3))
    ret2 = filter_self(fn2, list3)
    print('{}\n{}\n{}\n{}\n'.format('filter'.center(20, '-'), ret1, 'filter self'.center(20, '-'), ret2))


if __name__ == '__main__':
    main()
